/**
 * Created by ${PRODUCT_NAME}.
 * User: skylerparr
 * Date: 12/19/10
 * Time: 4:45 PM
 * To change this template use File | Settings | File Templates.
 */
package com.thoughtorigin.deeplink {
import com.asual.swfaddress.SWFAddressEvent;
import com.thoughtorigin.service.Message;

import com.thoughtorigin.service.Service;
import com.thoughtorigin.util.isBlank;

import flash.events.Event;
import flash.events.EventDispatcher;

public class ConfigurableDeeplinker extends EventDispatcher implements DeepLinker {

    private var _browserHistory: BrowserHistory;
    private var _delimiter: String = "/";
    private var _deeplinkString: String;
    private var _configs: Array;
    private var _defaultDeeplink: String;
    private var _errorDeeplink: String;
    private var _configuration: String;
    private var _primaryServiceName: String;

    public function set delimiter(value: String): void {
        _delimiter = value;
    }

    public function set defaultDeeplink(value: String): void {
        _defaultDeeplink = value;
    }

    public function get delimiter(): String {
        return _delimiter;
    }

    public function set errorDeeplink(value: String): void {
        _errorDeeplink = value;
    }

    public function set configuration(value: String): void {
        _configuration = value;
        _configs = _configuration.split(_delimiter);
    }

    public function get configs(): Array {
        return _configs;
    }

    protected function isPrimaryServiceSet(): Boolean {
        return !isBlank(_primaryServiceName);
    }

    public function set primaryService(value: String): void {
        _primaryServiceName = value;
    }

    public function ConfigurableDeeplinker() {
    }

    public function setDeepLink(message:Message):void {
        _deeplinkString = getDeeplinkString(message);

        browserHistory.setValue(_deeplinkString);
    }

    public function get deepLinkString():String {
        return _deeplinkString;
    }

    public function buildMessage(linkValue:String):Message {
        if(!linkValue) {
            return null;
        }

        if (linkValue.length <= 1) {
            var rawQuery:String = extractQueryString(browserHistory.getBaseURL());
            var parsedQuery:String = parseQueryString(rawQuery);
            if (!isBlank(parsedQuery) && queryHasValidKeys(rawQuery))
            {
                return buildMessage(parsedQuery);
            }
            return getDefaultCommand();
        }

        return createMessage(linkValue);
    }

    public function getDefaultCommand(): Message {
        var message: Message = createMessage(_defaultDeeplink);
        if(message != null) {
            message.isDeeplink = false;
        }
        return message;
    }

    private function createMessage(linkValue:String): Message {
        var message: Message = new Message();
        var values: Array = linkValue.split(_delimiter);
        var counter: int = 0;
        message.isDeeplink = true;

        for each(var config: String in _configs) {
            if(config) {
                message[config] = values[counter];
            }
            counter++;
        }

        if(isPrimaryServiceSet()) {
            message.serviceName = _primaryServiceName;
            //no need to handle the error link.  The primary services will handle it.
            return message;
        }

        return message;
    }

    public function init():void {
        browserHistory.addEventListener(SWFAddressEvent.INIT, setupDeeplinker);
    }

    protected function setupDeeplinker(e: Event): void {
        browserHistory.removeEventListener(SWFAddressEvent.INIT, init);

        browserHistory.setHistory(true);
        browserHistory.setStrict(false);
        browserHistory.addEventListener(SWFAddressEvent.CHANGE, addressChange);

    }

    protected function addressChange(e: SWFAddressEvent): void {
        var message: Message = buildMessage(browserHistory.getPath());
        if (message && !isBlank(browserHistory.getPath())) {
            _deeplinkString = getDeeplinkString(message);
            dispatchEvent(message);
            return;
        }

        message = buildMessage(_delimiter);
        if(message && isBlank(browserHistory.getPath())) {
            _deeplinkString = getDeeplinkString(message);
            dispatchEvent(message);
            return;
        }
    }

    protected function getDeeplinkString(message: Message): String {
        var retVal: String = "";
        var firstVarSet: Boolean = false;
        for each(var config: String in _configs) {
            if(!isBlank(config)) {
                if(message && message[config]) {
                    retVal += _delimiter + message[config];
                    firstVarSet = true;
                } else {
                    retVal += _delimiter
                }
            }
        }
        return retVal;
    }

    protected function get browserHistory(): BrowserHistory {
        if(!_browserHistory) {
            _browserHistory = SWFAddressProxy.instance;
        }
        return _browserHistory;
    }

    public function get queryString(): String {
        var message: Message = buildMessage(deepLinkString);
        var params: Array = [];
        for(var config: String in message) {
            if(!isBlank(config)) {
                if(message && message[config]) {
                    params.push(config + "=" + message[config]);
                }
            }
        }

        return "?" + params.join("&");
    }

    public function extractQueryString(baseUrl:String):String {
        var split:Array = baseUrl.split("?");
        if (split.length > 1) {
            return split[1];
        } else {
            return "";
        }
    }

    public function queryHasValidKeys(queryString:String):Boolean {
        var keys:Array = queryString.split("&").map(
                function(element:String, index:int, arr:Array):String {
                    return element.split("=")[0];
                });
        for each (var key:String in keys) {
            return _configs.indexOf(key) > -1;
        }
        return false;
    }

    public function parseQueryString(queryString:String):String {
        if (isBlank(queryString) || browserHistory.getPath().length > 1) {
            return "";
        }

        _deeplinkString = "";
        for each(var config: String in _configs) {
            if(config) {
                _deeplinkString += _delimiter + getParam(queryString, config);
            }
        }
        return _deeplinkString;
    }

    public function getParam(queryString:String, paramName:String):String {
        var params:Array = queryString.split("&");

        for (var i:int = 0; i < params.length; i++) {
            var param:String = params[i].split("=")[0];
            if (paramName == param) {
                return params[i].split("=")[1];
            }
        }

        return "";
    }
}
}
